package org.example.day05;

/**
 * 第二章节2.2.8.2:细化验证3个结论
 *      结论2: 当其他线程执行x对象中synchronized同步方法时，呈现同步效果
 */
public class MyThread2 {
    synchronized public void print(){
        System.out.println("getLock Time = " + System.currentTimeMillis() + " ThreadName = " + Thread.currentThread().getName());
        System.out.println("----------------------------");
        System.out.println("releaseLock Time = " + System.currentTimeMillis() + " ThreadName = " + Thread.currentThread().getName());
    }

    public static void main(String[] args) throws InterruptedException {
        Service2 service = new Service2();
        MyThread2 m2 = new MyThread2();
        Thread2A ta = new Thread2A(service, m2);
        ta.setName("A");
        ta.start();
        Thread.sleep(100); //确保A线程先拿到锁
        Thread2B tb = new Thread2B(m2);
        tb.setName("B");
        tb.start();
    }
}

class Service2 {
    //如果synchronized加在testMethod方法上,对应的锁是sv对象，无法达到互斥，这里用synchronized代码块，锁用的m2对象，和B线程调用print方法用到的是同一把锁，达到同步。
    public void testMethod(MyThread2 m2){
        synchronized (m2){
            try {
                System.out.println("getLock Time = " + System.currentTimeMillis() + " ThreadName = " + Thread.currentThread().getName());
                Thread.sleep(5000);
                System.out.println("releaseLock Time = " + System.currentTimeMillis() + " ThreadName = " + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Thread2A extends Thread{
    private Service2 sv;
    private MyThread2 m2;

    public Thread2A(Service2 sv, MyThread2 m2) {
        this.sv = sv;
        this.m2 = m2;
    }

    @Override
    public void run() {
        sv.testMethod(m2);
    }
}

class Thread2B extends Thread{
    private MyThread2 m2;

    public Thread2B(MyThread2 m2) {
        this.m2 = m2;
    }

    @Override
    public void run() {
        m2.print();
    }
}